/*
 *  The MIT License
 *
 *  Copyright 2013 Jyrki Puttonen. All rights reserved.
 *  Copyright 2013 Sony Mobile Communications AB. All rights reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 */
package com.sonymobile.tools.gerrit.gerritevents.dto.rest;

import com.sonymobile.tools.gerrit.gerritevents.GerritQueryException;
import com.sonymobile.tools.gerrit.gerritevents.GerritQueryHandler;
import com.sonymobile.tools.gerrit.gerritevents.dto.attr.Change;
import com.sonymobile.tools.gerrit.gerritevents.dto.attr.PatchSet;
import com.sonymobile.tools.gerrit.gerritevents.dto.events.ChangeBasedEvent;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Class to represent Topic related information.
 */
public class Topic {
    private static final Logger logger = LoggerFactory.getLogger(ChangeBasedEvent.class);

    private final String name;
    private Map<GerritQueryHandler, Map<Change, PatchSet>> changes = null;

    /**
     * Standard Constructor.
     *
     * @param name the topic name.
     */
    public Topic(String name) {
        this.name = name;
        this.changes = new HashMap<GerritQueryHandler, Map<Change, PatchSet>>();
    }

    /**
     * @return the name of topic.
     */
    public String getName() {
        return name;
    }

    /**
     * Query all change-patchset pairs related to this topic.
     *
     * @param gerritQueryHandler the query handler, responsible for the queries to gerrit.
     * @return the map of pairs change-patchset related to this topic.
     */
    public Map<Change, PatchSet> queryChanges(GerritQueryHandler gerritQueryHandler) {
        if (StringUtils.isEmpty(name)) {
            logger.error("Topic name can not be empty");
            return Collections.emptyMap();
        }

        Map<Change, PatchSet> result = new HashMap<Change, PatchSet>();
        try {
            List<JSONObject> jsonList = gerritQueryHandler.queryCurrentPatchSets("topic:{" + name + "}");
            for (JSONObject json : jsonList) {
                if (json.has("type") && "stats".equalsIgnoreCase(json.getString("type"))) {
                    continue;
                }
                if (json.has("currentPatchSet")) {
                    JSONObject currentPatchSet = json.getJSONObject("currentPatchSet");
                    result.put(new Change(json), new PatchSet(currentPatchSet));
                }
            }
        } catch (IOException e) {
            logger.error("IOException occured. ", e);
        } catch (GerritQueryException e) {
            logger.error("Bad query. ", e);
        }
        return result;
    }

    /**
     * Gets all change-patchset pairs related to this topic.
     * After first call data is cached.
     *
     * @param gerritQueryHandler the query handler, responsible for the queries to gerrit.
     * @return the map of pairs change-patchset related to this topic.
     */
    public Map<Change, PatchSet> getChanges(GerritQueryHandler gerritQueryHandler) {
        if (changes.containsKey(gerritQueryHandler)) {
            return changes.get(gerritQueryHandler);
        }
        Map<Change, PatchSet> result = queryChanges(gerritQueryHandler);
        changes.put(gerritQueryHandler, result);
        return result;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        Topic topic = (Topic)o;

        //CS IGNORE AvoidInlineConditionals FOR NEXT 1 LINES. REASON: Autogenerated Code.
        return name != null ? name.equals(topic.name) : topic.name == null;
    }

    @Override
    public int hashCode() {
        //CS IGNORE AvoidInlineConditionals FOR NEXT 1 LINES. REASON: Autogenerated Code.
        return name != null ? name.hashCode() : 0;
    }

    @Override
    public String toString() {
        return name;
    }
}
